/*
 * @Description:
 * @Author: maxyang
 * @Date: 2022-05-19 10:08:58
 * @LastEditTime: 2022-08-10 15:44:31
 * @LastEditors: liutq
 * @Reference:
 */
package goods

import (
	"errors"
	"fmt"
	"strconv"
	"time"

	"github.com/maxyang107/jinglan/common"
	"github.com/maxyang107/jinglan/model"
	"github.com/maxyang107/jinglan/model/user/repo"
)

type Goods struct {
	ID               uint      `gorm:"column:id; parimary_key" json:"id"`
	GoodsName        string    `gorm:"column:goods_name" json:"goods_name"`
	GoodsType        uint8     `gorm:"column:goods_type" json:"goods_type"`
	GoodsCate        uint8     `gorm:"column:goods_cate" json:"goods_cate"`
	GoodsKind        uint8     `gorm:"column:goods_kind" json:"goods_kind"`
	GoodsBlindCode   string    `gorm:"column:goods_blind_code" json:"goods_blind_code"`
	GoodsPrice       float64   `gorm:"column:goods_price" json:"goods_price"`
	GoodsRepoPrice   float64   `gorm:"column:goods_repo_price" json:"goods_repo_price"`
	GoodsRepoDay     uint8     `gorm:"column:goods_repo_day" json:"goods_repo_day"`
	GoodsListImg     string    `gorm:"column:goods_list_img" json:"goods_list_img"`
	GoodsD3Img       string    `gorm:"column:goods_d3_img" json:"goods_d3_img"`
	GoodsCirculation uint      `gorm:"column:goods_circulation" json:"goods_circulation"`
	GoodsStore       uint      `gorm:"column:goods_store" json:"goods_store"`
	GoodsAuthorUid   uint      `gorm:"column:goods_author_uid" json:"goods_author_uid"`
	GoodsDescribe    string    `gorm:"column:goods_describe" json:"goods_describe"`
	GoodsIssuer      string    `gorm:"column:goods_issuer" json:"goods_issuer"`
	GoodsAuthorized  string    `gorm:"column:goods_authorized" json:"goods_authorized"`
	GoodsOptionId    uint      `gorm:"column:goods_option_id" json:"goods_option_id"`
	Status           uint8     `gorm:"column:status" json:"status"`
	VshopUrl         string    `gorm:"column:vshop_url" json:"vshop_url"`
	Createtime       time.Time `gorm:"column:createtime" json:"createtime"`
	Updatetime       time.Time `gorm:"column:updatetime" json:"updatetime"`
	LuckyNum         uint      `gorm:"column:lucky_num" json:"lucky_num"`
	Drawtime         time.Time `gorm:"column:drawtime" `
}

type GoodsTmp struct {
	ID               uint      `gorm:"column:id; parimary_key" json:"ID"`
	GoodsName        string    `gorm:"column:goods_name" json:"GoodsName"`
	GoodsType        uint8     `gorm:"column:goods_type" json:"GoodsType"`
	GoodsCate        uint8     `gorm:"column:goods_cate" json:"GoodsCate"`
	GoodsKind        uint8     `gorm:"column:goods_kind" json:"GoodsKind"`
	GoodsBlindCode   string    `gorm:"column:goods_blind_code" json:"GoodsBlindCode"`
	GoodsPrice       float64   `gorm:"column:goods_price" json:"GoodsPrice"`
	GoodsRepoPrice   float64   `gorm:"column:goods_repo_price" json:"GoodsRepoPrice"`
	GoodsRepoDay     uint8     `gorm:"column:goods_repo_day" json:"GoodsRepoDay"`
	GoodsListImg     string    `gorm:"column:goods_list_img" json:"GoodsListImg"`
	GoodsD3Img       string    `gorm:"column:goods_d3_img" json:"GoodsD3Img"`
	GoodsCirculation uint      `gorm:"column:goods_circulation" json:"GoodsCirculation"`
	GoodsStore       uint      `gorm:"column:goods_store" json:"GoodsStore"`
	GoodsAuthorUid   uint      `gorm:"column:goods_author_uid" json:"GoodsAuthorUid"`
	GoodsDescribe    string    `gorm:"column:goods_describe" json:"GoodsDescribe"`
	GoodsIssuer      string    `gorm:"column:goods_issuer" json:"GoodsIssuer"`
	GoodsAuthorized  string    `gorm:"column:goods_authorized" json:"GoodsAuthorized"`
	GoodsOptionId    uint      `gorm:"column:goods_option_id" json:"GoodsOptionId"`
	Status           uint8     `gorm:"column:status" json:"Status"`
	Createtime       time.Time `gorm:"column:createtime" json:"Createtime"`
	Updatetime       time.Time `gorm:"column:updatetime" json:"Updatetime"`
	Username         string    `gorm:"column:username" json:"Username"`
	Headimg          string    `gorm:"column:headimg" json:"Headimg"`
	VshopUrl         string    `gorm:"column:vshop_url" json:"VshopUrl"`
	Drawtime         time.Time `gorm:"column:drawtime" json:"Drawtime"`
	LuckyNum         uint      `gorm:"column:lucky_num" json:"lucky_num"`
}

type GoodsTmp_ struct {
	ID               uint      `gorm:"column:id; parimary_key" json:"id"`
	GoodsName        string    `gorm:"column:goods_name" json:"goods_name"`
	GoodsType        uint8     `gorm:"column:goods_type" json:"goods_type"`
	GoodsCate        uint8     `gorm:"column:goods_cate" json:"goods_cate"`
	GoodsIssuer      string    `gorm:"column:goods_issuer" json:"GoodsIssuer"`
	GoodsAuthorized  string    `gorm:"column:goods_authorized" json:"GoodsAuthorized"`
	GoodsPrice       float64   `gorm:"column:goods_price" json:"goods_price"`
	GoodsListImg     string    `gorm:"column:goods_list_img" json:"goods_list_img"`
	GoodsCirculation uint      `gorm:"column:goods_circulation" json:"goods_circulation"`
	GoodsStore       uint      `gorm:"column:goods_store" json:"goods_store"`
	Createtime       time.Time `gorm:"column:createtime" json:"createtime"`
	Username         string    `gorm:"column:username" json:"username"`
	VshopUrl         string    `gorm:"column:vshop_url" json:"vshop_url"`
	Headimg          string    `gorm:"column:headimg" json:"headimg"`
}

type GoodsList struct {
	GoodsCate uint8 `json:"goods_cate" `
	Page      uint  `json:"page" `
	PerPage   uint  `json:"per_page"`
	Total     uint
	Data      []GoodsTmp_
}

type GoodsTmp2_ struct {
	ID               uint       `gorm:"column:id; parimary_key" json:"id"`
	GoodsName        string     `gorm:"column:goods_name" json:"goods_name"`
	GoodsType        uint8      `gorm:"column:goods_type" json:"goods_type"`
	GoodsCate        uint8      `gorm:"column:goods_cate" json:"goods_cate"`
	GoodsIssuer      string     `gorm:"column:goods_issuer" json:"GoodsIssuer"`
	GoodsAuthorized  string     `gorm:"column:goods_authorized" json:"GoodsAuthorized"`
	GoodsPrice       float64    `gorm:"column:goods_price" json:"goods_price"`
	GoodsListImg     string     `gorm:"column:goods_list_img" json:"goods_list_img"`
	GoodsCirculation uint       `gorm:"column:goods_circulation" json:"goods_circulation"`
	GoodsStore       uint       `gorm:"column:goods_store" json:"goods_store"`
	Createtime       time.Time  `gorm:"column:createtime" json:"createtime"`
	Username         string     `gorm:"column:username" json:"username"`
	Headimg          string     `gorm:"column:headimg" json:"headimg"`
	VshopUrl         string     `gorm:"column:vshop_url" json:"vshop_url"`
	Drawtime         *time.Time `gorm:"column:drawtime" json:"drawtime"`
	DrawStatus       uint8      `gorm:"column:draw_status" json:"draw_status"`
	DrawNum          uint       `json:"draw_num"`
}

type GoodsList1 struct {
	GoodsCate uint8 `json:"goods_cate" `
	Page      uint  `json:"page" `
	PerPage   uint  `json:"per_page"`
	Total     uint
	Data      []GoodsTmp2_
}

func GetGoodsList(query_ common.GoodsList) GoodsList {
	var goodslist GoodsList
	goodslist.Total = getTotal(query_)
	goodslist.Page = query_.Page
	goodslist.PerPage = query_.PerPage

	model.Db.Table("goods").Select("goods.*, user.username,user.headimg").Joins("left join user on user.id=goods.goods_author_uid").Where(&Goods{GoodsCate: query_.GoodsCate, Status: 1}).Limit(query_.PerPage).Offset((query_.Page - 1) * query_.PerPage).Order("id desc").Scan(&goodslist.Data)

	return goodslist
}

func GetAdminGoodsList(query_ common.AdminGoodsList) GoodsList {
	var goodslist GoodsList
	goodslist.Total = getAdminTotal(query_)
	goodslist.Page = query_.Page
	goodslist.PerPage = query_.PerPage
	tx := model.Db.Table("goods").Select("goods.*, user.username,user.headimg").Joins("left join user on user.id=goods.goods_author_uid")
	if query_.Key != "" {
		tx = tx.Where(fmt.Sprintf(" goods.goods_name like %s ", ("'%" + query_.Key + "%'")))
	}
	if query_.GoodsCate != 0 {
		tx = tx.Where(fmt.Sprintf(" goods.goods_cate = %d ", query_.GoodsCate))
	}
	tx.Limit(query_.PerPage).Offset((query_.Page - 1) * query_.PerPage).Scan(&goodslist.Data)
	return goodslist
}

func getAdminTotal(query_ common.AdminGoodsList) uint {
	var total uint
	if query_.Key != "" {
		model.Db.Model(&Goods{}).Where(&Goods{GoodsCate: query_.GoodsCate}).Where(fmt.Sprintf(" goods.goods_name like %s ", ("'%" + query_.Key + "%'"))).Count(&total)
	} else {
		model.Db.Model(&Goods{}).Where(&Goods{GoodsCate: query_.GoodsCate}).Count(&total)
	}

	return total
}

func getTotal(query_ common.GoodsList) uint {
	key := strconv.Itoa(int(query_.GoodsCate)) + "total"

	s := model.GetKey(key)
	pageNum_, _ := strconv.Atoi(s)
	if pageNum_ > 0 {
		return uint(pageNum_)
	}
	var total uint
	model.Db.Model(&Goods{}).Where(&Goods{GoodsCate: query_.GoodsCate, Status: 1}).Count(&total)
	pageNum := total / query_.PerPage
	if total%query_.PerPage != 0 {
		pageNum++
	}
	model.SetKey(key, strconv.Itoa(int(pageNum)), 300*time.Second)
	return pageNum
}

func GetGoodsDetail(id_ int) GoodsTmp {
	var goodsDetail GoodsTmp
	model.Db.Table("goods").Select("goods.*, user.username,user.headimg").Joins("left join user on user.id=goods.goods_author_uid").First(&goodsDetail, &Goods{ID: uint(id_), Status: 1})

	return goodsDetail
}

func GetAdminGoodsDetail(id_ int) GoodsTmp {
	var goodsDetail GoodsTmp
	model.Db.Table("goods").Select("goods.*, user.username,user.headimg").Joins("left join user on user.id=goods.goods_author_uid").First(&goodsDetail, &Goods{ID: uint(id_)})
	return goodsDetail
}

func GetGoodsListForDraw(query_ common.GoodsList) GoodsList1 {
	var goodslist GoodsList1
	goodslist.Total = getTotal(query_)
	goodslist.Page = query_.Page
	goodslist.PerPage = query_.PerPage
	model.Db.Table("goods").Select("goods.*, user.username,user.headimg,draw_record.draw_status ").Joins("inner join user on user.id=goods.goods_author_uid").Joins(fmt.Sprintf("left join draw_record on goods.id = draw_record.goods_id and draw_record.user_id = %d", query_.UserId)).Where(&Goods{GoodsCate: query_.GoodsCate, Status: 1}).Limit(query_.PerPage).Offset((query_.Page - 1) * query_.PerPage).Order("id desc").Scan(&goodslist.Data)

	for k, v := range goodslist.Data {
		model.Db.Table("draw_record").Where(&DrawRecord{GoodsId: v.ID}).Count(&v.DrawNum)
		ii := GetIrrigation(v.ID)
		goodslist.Data[k].DrawNum = v.DrawNum + ii.IrrigationNum

		if v.DrawStatus == 2 {
			var num int
			model.Db.Table("my_collect").Where("goods_id = ?", v.ID).Where("owner_uid = ?", query_.UserId).Count(&num)

			if num > 0 {
				goodslist.Data[k].DrawStatus = 4
			}
		}
	}
	return goodslist
}

func AddGoods(param_ *common.Goods, chainInfo *common.GoodsChainInfo) error {
	var tmp Goods

	model.Db.Where(&Goods{GoodsName: param_.GoodsName, GoodsKind: param_.GoodsKind, GoodsDescribe: param_.GoodsDescribe}).First(&tmp)

	if tmp.ID > 0 {
		return errors.New("商品已存在，请勿重复上传")
	}
	tx := model.Db.Begin()
	if err := tx.Create(param_).Error; err != nil {
		tx.Rollback()
		return err
	}

	//保存链上信息
	chainInfo.GoodsId = param_.ID

	if err := tx.Create(&chainInfo).Error; err != nil {
		tx.Rollback()
		return err
	}

	tx.Commit()
	return nil
}

func ModifyGoods(param_ *common.Goods) error {
	var tmp Goods

	model.Db.Where(&Goods{ID: param_.ID}).First(&tmp)

	if tmp.ID == 0 {
		return errors.New("商品不存在")
	}

	if tmp.GoodsKind == 3 && tmp.GoodsRepoPrice == 0 && param_.GoodsRepoPrice != 0 {
		var tmpCollect common.Mycollect
		if param_.GoodsRepoDay == 0 {
			param_.GoodsRepoDay = 7
		}
		now := time.Now()
		tmpCollect.RepoStartTime = now.AddDate(0, 0, int(param_.GoodsRepoDay))
		tmpCollect.GoodsId = param_.ID
		tmpCollect.RepoStatus = 1
		repo.UpdateMyCollectForRepo(&tmpCollect)

		//发送通知短信todo……

	}
	if err := model.Db.Table("goods").Where(&Goods{ID: param_.ID}).Update(&param_).Error; err != nil {
		return err
	}
	status := make(map[string]interface{})
	status["status"] = param_.Status
	if err := model.Db.Table("goods").Where(&Goods{ID: param_.ID}).Update(status).Error; err != nil {
		return err
	}
	return nil
}

func GetGoodsByImgUrl(img string) *GoodsTmp {
	var goods_ GoodsTmp

	model.Db.Table("goods").Where(&Goods{GoodsListImg: img}).First(&goods_)

	return &goods_
}

func ModifyStock(goodsId uint, num uint, op bool) error {
	var tmp Goods
	model.Db.Model(&Goods{}).Where(&Goods{ID: goodsId}).First(&tmp)
	if tmp.ID == 0 {
		return errors.New("商品不存在")
	}
	if op {
		tmp.GoodsStore = tmp.GoodsStore + num
	} else {
		if tmp.GoodsStore < num {
			return errors.New("库存不足")
		}
		tmp.GoodsStore = tmp.GoodsStore - num
	}
	if err := model.Db.Model(&Goods{}).Update(tmp).Error; err != nil {
		return err
	}
	return nil
}
